<?php

namespace app\admin\service\common\token;

use think\facade\Db;
use think\facade\Log;

class DbTokenRepository implements TokenRepositoryInterface
{
    protected string $tableName = 'admin_token';

    public function save(array $tokenInfo, string $type): void
    {
        try {
            $data = [
                'user_id' => $tokenInfo['id'],
                'username' => $tokenInfo['username'] ?? '',
                'access_token' => $tokenInfo['accessToken'] ?? '',
                'refresh_token' => $tokenInfo['refreshToken'] ?? '',
                'expired' => $tokenInfo['expireTime'] ?? 0,
                'expired_date' => date('Y-m-d H:i:s', $tokenInfo['expireTime']),
                'expire_time' => $tokenInfo['expireTime'] ?? 0,
                'refresh_expire_time' => $tokenInfo['refreshExpireTime'] ?? 0,
                'type' => $type,
                'online' => time(),
                'status' => 1,
                'create_time' => time(),
                'update_time' => time(),
            ];

            Db::name($this->tableName)->insert($data);
            trace("Token saved to database: {$type} for user {$data['username']}");
        } catch (\Exception $e) {
            throw $e;
        }
    }

    public function find(string $token, string $type): ?array
    {
        try {
            $result = Db::name($this->tableName)
                ->where($type.'_token', $token)
                ->find();

            return $result ?: null;
        } catch (\Exception $e) {
            Log::error("Failed to find token: " . $e->getMessage());
            return null;
        }
    }

    public function findByUser(string $username): array
    {
        try {
            return Db::name($this->tableName)
                ->where('username', $username)
                ->select()
                ->toArray();
        } catch (\Exception $e) {
            Log::error("Failed to find tokens by user: " . $e->getMessage());
            return [];
        }
    }

    public function deleteByUser(string $username): void
    {
        try {
            Db::name($this->tableName)
                ->where('username', $username)
                ->delete();

            trace("All tokens deleted for user: {$username}");
        } catch (\Exception $e) {
            Log::error("Failed to delete tokens by user: " . $e->getMessage());
            throw $e;
        }
    }

    public function delete(string $token, string $type): void
    {
        try {
            Db::name($this->tableName)
                ->where($type.'_token', $token)
                ->delete();

            trace("Token deleted from database: {$type}");
        } catch (\Exception $e) {
            Log::error("Failed to delete token: " . $e->getMessage());
            throw $e;
        }
    }

    public function updateOnline(string $token): void
    {
        try {
            Db::name($this->tableName)
                ->where('access_token', $token)
                ->update([
                    'online' => time(),
                ]);

            trace("Token online status has updated for token: {$token}");
        } catch (\Exception $e) {
            Log::error("Failed to update token online status: " . $e->getMessage());
            throw $e;
        }
    }

    public function deleteExpired(): void
    {
        try {
            $currentTime = time();
            $deletedCount = Db::name($this->tableName)
                ->where('expire_time', '<', $currentTime)
                ->delete();

            trace("Deleted {$deletedCount} expired tokens");
        } catch (\Exception $e) {
            Log::error("Failed to delete expired tokens: " . $e->getMessage());
            throw $e;
        }
    }


}